<script lang="tsx" name="ApiSelect">
  /**
   *  title
   * @description: description
   * @author SunYanMing<95317356@qq.com>
   * @property {Boolean} props desc info
   * @example <ApiSelect />
   * @date 2023/11/16
   */
  import { defineComponent, onMounted, ref, watch, toValue, computed } from 'vue';
  import { get, omit, noop, cloneDeep, throttle } from 'lodash-es';

  export default defineComponent({
    name: 'ApiSelect',

    inheritAttrs: true,
    props: {
      prop: {
        type: String,
        default: '',
      },
      formData: {
        type: Object,
        default: () => ({}),
      },

      modelValue: {
        type: [String, Number, Array],
        default: undefined,
      },
      // 携带参数 返回一个携带对象
      params: {
        type: [Function, Object],
        default: noop,
      },
      apiBefore: {
        type: Function,
        default: noop,
      },
      apiAfter: {
        type: Function,
        default: noop,
      },
      api: {
        type: Function,
        default: null,
      },
      labelField: {
        type: String,
        default: 'label',
      },
      valueField: {
        type: String,
        default: 'value',
      },
      resultField: {
        type: String,
        default: 'rows',
      },
      onChange: {
        type: Function,
        default: noop,
      },
      componentProps: {
        type: Object,
        default: () => ({}),
      },
    },

    emits: ['update:modelValue'],
    setup(props, cxt) {
      // console.log(props, cxt);
      const options = ref([]);

      const value = ref(props.modelValue);

      const colApiOptionsProxy = throttle(async () => {
        const { api, params } = props;
        if (typeof api === 'function') {
          let _params = {};
          if (typeof params === 'function') {
            _params = params(cloneDeep(props.formData)) ?? {};
          } else {
            _params = props.apiBefore(params, cloneDeep(props.formData)) ?? params;
          }
          api(_params ?? {}).then((res) => {
            const _res = props.apiAfter(res) ?? res;
            // console.log(_res);
            options.value = get(_res, props.resultField) ?? [];
          });
        }
      }, 800);

      watch(
        () => value.value,
        (val) => {
          cxt.emit('update:modelValue', toValue(val));
        },
        {
          immediate: true,
        },
      );
      onMounted(() => {
        // 监听某字典发生变化时触发拉取api代理列表
        colApiOptionsProxy();
        if (props.componentProps.watchPropsChangeApi) {
          let _oldValue = {};
          watch(
            () => props.formData,
            (value) => {
              const _value = toValue(value);
              const keys =
                typeof props.componentProps.watchPropsChangeApi === 'string'
                  ? [props.componentProps.watchPropsChangeApi]
                  : props.componentProps.watchPropsChangeApi;
              keys.map((key: string) => {
                // console.log(key, get(_value, key), get(_oldValue, key));
                if (get(_value, key) !== get(_oldValue, key)) {
                  colApiOptionsProxy();
                }
              });

              _oldValue = cloneDeep(toValue(value) ?? {});
            },
            {
              // immediate: true,
              deep: true,
            },
          );
        }
      });

      const rows = computed(() => {
        return options.value.map((el: any) => ({
          ...el,
          // label: el[props.labelField],
          // value: el[props.valueField],
        }));
      });

      const row = computed(() => {
        return rows.value?.find((e) => e[props.valueField] == value.value);
      });

      return {
        value,
        rows,
        row,
        omit,
      };
    },
  });
</script>
<template>
  <el-tree-select
    v-model="value"
    v-bind="{ ...omit($props, 'onChange'), ...$attrs }"
    @change="$props.onChange"
    :data="rows"
  >
    <template #[key]="slotData" v-for="key in Object.keys($slots)">
      <slot :name="key" v-bind="slotData || {}"></slot>
    </template>
  </el-tree-select>
</template>

<style scoped></style>
